// Infrastructure/Repositories/OperationLogRepository.cs
using Microsoft.EntityFrameworkCore;
using UniversalAdmin.Domain.Entities;
using UniversalAdmin.Domain.Repositories;
using UniversalAdmin.Infrastructure.Data;

namespace UniversalAdmin.Infrastructure.Repositories;

public class OperationLogRepository : BaseRepository<OperationLog>, IOperationLogRepository
{
  public OperationLogRepository(UniversalAdminDbContext context) : base(context) { }

  public async Task<IEnumerable<OperationLog>> GetLogsByUserIdAsync(int userId)
  {
    return await _context.OperationLogs
        .Where(l => l.UserId == userId)
        .OrderByDescending(l => l.CreatedAt)
        .ToListAsync();
  }

  public async Task<IEnumerable<OperationLog>> GetLogsByResourceAsync(string resource, int? resourceId = null)
  {
    var query = _context.OperationLogs
        .Where(l => l.Resource == resource);

    if (resourceId.HasValue)
    {
      query = query.Where(l => l.ResourceId == resourceId.Value);
    }

    return await query
        .OrderByDescending(l => l.CreatedAt)
        .ToListAsync();
  }

  public async Task<(IEnumerable<OperationLog> Items, int TotalCount)> SearchLogsAsync(
      string? action = null,
      string? resource = null,
      int? resourceId = null,
      int? userId = null,
      DateTime? startDate = null,
      DateTime? endDate = null,
      int pageIndex = 1,
      int pageSize = 10)
  {
    IQueryable<OperationLog> query = _context.OperationLogs
    .Include(l => l.User)          // 导航属性
    .OrderByDescending(l => l.CreatedAt);

    if (!string.IsNullOrWhiteSpace(action))
    {
      query = query.Where(l => l.Action == action);
    }

    if (!string.IsNullOrWhiteSpace(resource))
    {
      query = query.Where(l => l.Resource == resource);
    }

    if (resourceId.HasValue)
    {
      query = query.Where(l => l.ResourceId == resourceId.Value);
    }

    if (userId.HasValue)
    {
      query = query.Where(l => l.UserId == userId.Value);
    }

    if (startDate.HasValue)
    {
      query = query.Where(l => l.CreatedAt >= startDate.Value);
    }

    if (endDate.HasValue)
    {
      query = query.Where(l => l.CreatedAt <= endDate.Value);
    }

    var totalCount = await query.CountAsync();

    var items = await query
        .OrderByDescending(l => l.CreatedAt)
        .Skip((pageIndex - 1) * pageSize)
        .Take(pageSize)
        .AsNoTracking()
        .ToListAsync();

    return (items, totalCount);
  }

  public async Task<(IEnumerable<OperationLog> Items, int TotalCount)>
  SearchWithUserAsync(string? username, string? action, string? resource,
                      DateTime? startDate, DateTime? endDate,
                      int pageIndex, int pageSize)
  {
    // ① 统一转 UTC，避免 PostgreSQL 报错
    var startUtc = startDate?.ToUniversalTime();
    var endUtc = endDate?.ToUniversalTime();

    var query = _context.OperationLogs
        .Include(l => l.User)   // 联表拿用户名
        .AsNoTracking();

    if (!string.IsNullOrWhiteSpace(username))
      query = query.Where(l => l.User != null &&
                               l.User.Username.Contains(username));

    if (!string.IsNullOrWhiteSpace(action))
      query = query.Where(l => l.Action.Contains(action));

    if (!string.IsNullOrWhiteSpace(resource))
      query = query.Where(l => l.Resource != null &&
                               l.Resource.Contains(resource));

    if (startUtc.HasValue)
      query = query.Where(l => l.CreatedAt >= startUtc.Value);

    if (endUtc.HasValue)
      query = query.Where(l => l.CreatedAt <= endUtc.Value);

    var total = await query.CountAsync();

    var items = await query
        .OrderByDescending(l => l.CreatedAt)
        .Skip((pageIndex - 1) * pageSize)
        .Take(pageSize)
        .ToListAsync();

    return (items, total);
  }

  public async Task<int> CleanOldLogsAsync(DateTime cutoffDate)
  {
    var logsToDelete = await _context.OperationLogs
        .Where(l => l.CreatedAt < cutoffDate)
        .ToListAsync();

    _context.OperationLogs.RemoveRange(logsToDelete);
    return await _context.SaveChangesAsync();
  }
}